package com.cantor.provider.handler;

import cn.hutool.core.util.StrUtil;
import com.cantor.common.exception.ServiceInvokeException;
import com.cantor.core.message.CantorRequestMessage;
import com.cantor.core.message.CantorResponseMessage;
import com.cantor.provider.invoker.ServiceInvoker;
import com.cantor.provider.pojo.ServiceBoat;
import com.cantor.provider.regsitry.ServiceRegistrant;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;

/**
 * 服务端处理器, 处理Request事件
 * 这个处理器是非阻塞的,影响性能,已弃用,请移步 com.cantor.provider.handler.AsyncCantorRequestMessageHandler
 */
@Slf4j
@ChannelHandler.Sharable
@Deprecated
public class CantorRequestMessageHandler extends SimpleChannelInboundHandler<CantorRequestMessage> {

    // ServiceRegistrant内部维护的是ConcurrentHashMap,是线程安全的
    private final ServiceRegistrant serviceRegistrant;

    // 负责协调ServiceBoat中参数的服务执行器
    private final ServiceInvoker serviceInvoker;

    public CantorRequestMessageHandler(ServiceRegistrant serviceRegistrant, ServiceInvoker serviceInvoker) {
        this.serviceRegistrant = serviceRegistrant;
        this.serviceInvoker = serviceInvoker;
    }

    // 当有客户端连接来后, 打印客户端的地址
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        log.info("客户端{}成功连接到了Provider{}", ctx.channel().remoteAddress(), ctx.channel().localAddress());
        super.handlerAdded(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, CantorRequestMessage req) throws Exception {
        log.debug("Provider 接收到了请求");
        System.out.println(req);
        String interfaceName = req.getInterfaceName();
        if (StrUtil.isNotEmpty(req.getServiceVersion())) {
            interfaceName += ":" + req.getServiceVersion();
        }
        // 获取ServiceBoat
        ServiceBoat serviceBoat = serviceRegistrant.getBoat(interfaceName);
        // 获取XXXServiceImpl
        Object impl = serviceBoat.getServiceImpl();
        // 获取具体方法
        Method method = impl.getClass().getDeclaredMethod(req.getMethodName(), req.getParameterTypes());
        // 准备Response的Builder
        CantorResponseMessage.CantorResponseMessageBuilder builder = CantorResponseMessage.builder();
        // 使用invoker来执行
        try {
            Object result = serviceInvoker.invoke(serviceBoat.getServiceImpl(), req.getMethodName(), req.getParameterTypes(), req.getParameterValue(), serviceBoat);
            // 只有出现ServiceInvokeException, 才是服务调用出现真实异常(防止用户的服务返回值本身就是Exception类型)
            if (result instanceof ServiceInvokeException) {
                throw new Exception(((Exception) result).getMessage());
            }
            builder.returnValue(result);
        } catch (Exception e) {
            builder.exceptionValue(new Exception(e.getMessage())); // 只返回基本的信息, 防止返回整个异常链导致序列化字节太长.
            log.error("Provider调用该服务失败, 如果是java.lang.reflect.InvocationTargetException, 那么大概率是服务本身代码异常.");
            log.error(e.getMessage());
        }
        // build Response消息对象
        CantorResponseMessage responseMessage = builder.build();
        responseMessage.setSequenceId(req.getSequenceId()); // 回复这个请求里带的sequenceId
        // 回复客户端
        ctx.channel().writeAndFlush(responseMessage);
        // 释放资源
        ReferenceCountUtil.release(req);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        log.error("处理CantorRequest请求时出错,如果只是客户端连接断开,请忽略");
        ctx.close();
    }
}
